package com.powergisol.gis.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.powergisol.gis.dao.BoreholeQueryMapper;
import com.powergisol.gis.dto.*;
import com.powergisol.gis.entity.TabArea;
import com.powergisol.gis.geom.GeoPoint;
import com.powergisol.gis.geom.GeoPolygon;
import com.powergisol.gis.geom.SpatialRelationship;
import com.powergisol.gis.service.BoreholeQueryService;
import com.powergisol.gis.util.Result;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.Future;

@Service
public class BoreholeQueryServiceImpl implements BoreholeQueryService {
    @Autowired
    BoreholeQueryMapper boreholeQueryMapper;

    @Override
    public List<TabArea> getArea(QueryDataDTO dto) {
        TabArea tabArea = new TabArea();
        if(StringUtils.isNotBlank(dto.getCode())){
            Integer grade = dto.getGrade();
            switch (grade){
                case 1:
                    tabArea.setCode(dto.getCode().substring(0,2));
                    tabArea.setGrade(2);
                    break;
                case 2:
                    tabArea.setCode(dto.getCode().substring(0,4));
                    tabArea.setGrade(3);
                    break;
                default:
                    break;
            }
        }
        return boreholeQueryMapper.getArea(tabArea);
    }

    @Override
    public List<ZkDataDTO> boreHole(QueryDataDTO dto) {
        String code = dto.getCode();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            dto.setCode(getCodes(code));
        }
//        if(null != dto.getPage() && null != dto.getLimit()){
//            dto.setPage((dto.getPage()-1)*dto.getLimit());
//        }
        List<ZkDataDTO> list = boreholeQueryMapper.boreHole3D(dto);
        //过滤点范围
        SpatialRelationship spatialRelationship = new SpatialRelationship();
        List<GeoPoint> pointList = new ArrayList<>();
        List<double[]> zkfw = dto.getScope();
        List<ZkDataDTO> listZks = new ArrayList<>();
        //根据工程名称去重
        if(null !=zkfw && !zkfw.isEmpty()){
            for (ZkDataDTO o : list){
                GeoPoint point = new GeoPoint(Double.valueOf(o.getZKX()),Double.valueOf(o.getZKY()));
                Map<String,Object> properties = new HashMap<>();
                properties.put("TCCDSD",StringUtils.isBlank(o.getTCCDSD())?"":o.getTCCDSD());
                properties.put("TCHD",StringUtils.isBlank(o.getTCHD())?"":o.getTCHD());
                properties.put("TCMC",StringUtils.isBlank(o.getTCMC())?"":o.getTCMC());
                properties.put("ZKBG",StringUtils.isBlank(o.getZKBG())?"":o.getZKBG());
                properties.put("ZKSD",StringUtils.isBlank(o.getZKSD())?"":o.getZKSD());
                properties.put("ZKZJ",StringUtils.isBlank(o.getZKZJ())?"":o.getZKZJ());
                properties.put("dataIndex",o.getDataIndex()+"");
                properties.put("settingId",o.getSettingId()+"");
                properties.put("ZKBH",StringUtils.isBlank(o.getZKBH())?"":o.getZKBH());
                properties.put("GCMC",StringUtils.isBlank(o.getGCMC())?"":o.getGCMC());
                properties.put("markerColor",StringUtils.isBlank(o.getMarkerColor())?"":o.getMarkerColor());
                point.setProperties(properties);
                pointList.add(point);
            }
            double[][] doubles = zkfw.toArray(new double[zkfw.size()][2]);
            GeoPolygon geoPolygon = new GeoPolygon(doubles);
            List<GeoPoint> intersects = spatialRelationship.intersects(pointList, geoPolygon);
            //组装数据
            for (GeoPoint geoPoint:intersects) {
//                Map<String, Object> map = new HashMap<String, Object>((Map) geoPoint.getProperties());
//                map.remove("the_geom");
//                ZkDataDTO zkDataDTO = JSON.parseObject(JSON.toJSONString(map), ZkDataDTO.class);
                ZkDataDTO zkDataDTO = new ZkDataDTO();
                zkDataDTO.setDataIndex(geoPoint.getProperties().getProperty("dataIndex"));
                zkDataDTO.setGCMC(geoPoint.getProperties().getProperty("GCMC"));
                zkDataDTO.setSettingId(geoPoint.getProperties().getProperty("settingId"));
                zkDataDTO.setTCCDSD(geoPoint.getProperties().getProperty("TCCDSD"));
                zkDataDTO.setTCHD(geoPoint.getProperties().getProperty("TCHD"));
                zkDataDTO.setTCMC(geoPoint.getProperties().getProperty("TCMC"));
                zkDataDTO.setZKBG(geoPoint.getProperties().getProperty("ZKBG"));
                zkDataDTO.setZKBH(geoPoint.getProperties().getProperty("ZKBH"));
                zkDataDTO.setZKSD(geoPoint.getProperties().getProperty("ZKSD"));
                zkDataDTO.setZKX(String.valueOf(geoPoint.getX()));
                zkDataDTO.setZKZJ(geoPoint.getProperties().getProperty("ZKZJ"));
                zkDataDTO.setMarkerColor(geoPoint.getProperties().getProperty("markerColor"));
                zkDataDTO.setZKY(String.valueOf(geoPoint.getY()));
                listZks.add(zkDataDTO);
            }
            return listZks;
        }
        return list;
    }

    @Override
    public Result boreHoleList(QueryDataDTO dto) {
        Result r = new Result();
        String code = dto.getCode();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            dto.setCode(getCodes(code));
        }
        if(null != dto.getPage() && null != dto.getLimit()){
            dto.setPage((dto.getPage()-1)*dto.getLimit());
        }
        List<ZkDataDTO> list = boreholeQueryMapper.boreHole2D(dto);
        //过滤点范围
        SpatialRelationship spatialRelationship = new SpatialRelationship();
        List<GeoPoint> pointList = new ArrayList<>();
        List<double[]> zkfw = dto.getScope();
        List<ZkDataDTO> listZks = new ArrayList<>();
        if(null !=zkfw && !zkfw.isEmpty()){
            for (ZkDataDTO o : list){
                GeoPoint point = new GeoPoint(Double.valueOf(o.getZKX()),Double.valueOf(o.getZKY()));
                Map<String,Object> properties = new HashMap<>();
                properties.put("TCCDSD",StringUtils.isBlank(o.getTCCDSD())?"":o.getTCCDSD());
                properties.put("TCHD",StringUtils.isBlank(o.getTCHD())?"":o.getTCHD());
                properties.put("TCMC",StringUtils.isBlank(o.getTCMC())?"":o.getTCMC());
                properties.put("ZKBG",StringUtils.isBlank(o.getZKBG())?"":o.getZKBG());
                properties.put("ZKSD",StringUtils.isBlank(o.getZKSD())?"":o.getZKSD());
                properties.put("ZKZJ",StringUtils.isBlank(o.getZKZJ())?"":o.getZKZJ());
                properties.put("dataIndex",o.getDataIndex()+"");
                properties.put("settingId",o.getSettingId()+"");
                properties.put("ZKBH",StringUtils.isBlank(o.getZKBH())?"":o.getZKBH());
                properties.put("GCMC",StringUtils.isBlank(o.getGCMC())?"":o.getGCMC());
                point.setProperties(properties);
                pointList.add(point);
            }
            double[][] doubles = zkfw.toArray(new double[zkfw.size()][2]);
            GeoPolygon geoPolygon = new GeoPolygon(doubles);
            List<GeoPoint> intersects = spatialRelationship.intersects(pointList, geoPolygon);
            //组装数据
            for (GeoPoint geoPoint:intersects) {
                ZkDataDTO zkDataDTO = new ZkDataDTO();
                zkDataDTO.setDataIndex(geoPoint.getProperties().getProperty("dataIndex"));
                zkDataDTO.setGCMC(geoPoint.getProperties().getProperty("GCMC"));
                zkDataDTO.setSettingId(geoPoint.getProperties().getProperty("settingId"));
                zkDataDTO.setTCCDSD(geoPoint.getProperties().getProperty("TCCDSD"));
                zkDataDTO.setTCHD(geoPoint.getProperties().getProperty("TCHD"));
                zkDataDTO.setTCMC(geoPoint.getProperties().getProperty("TCMC"));
                zkDataDTO.setZKBG(geoPoint.getProperties().getProperty("ZKBG"));
                zkDataDTO.setZKBH(geoPoint.getProperties().getProperty("ZKBH"));
                zkDataDTO.setZKSD(geoPoint.getProperties().getProperty("ZKSD"));
                zkDataDTO.setZKX(String.valueOf(geoPoint.getX()));
                zkDataDTO.setZKZJ(geoPoint.getProperties().getProperty("ZKZJ"));
                zkDataDTO.setZKY(String.valueOf(geoPoint.getY()));
                listZks.add(zkDataDTO);
            }
            r.setData(listZks);
            return r;
        }
        r.setData(list);
        return r;
    }

    @Override
    public List<ZkPointDataDTO> boreHolePoint(QueryDataDTO dto) {
        String code = dto.getCode();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            dto.setCode(getCodes(code));
        }
        List<ZkPointDataDTO> list = boreholeQueryMapper.boreHolePoint(dto);
        //过滤点范围
        SpatialRelationship spatialRelationship = new SpatialRelationship();
        List<GeoPoint> pointList = new ArrayList<>();
        List<double[]> zkfw = dto.getScope();
        List<ZkPointDataDTO> listZks = new ArrayList<>();
        if(null !=zkfw && !zkfw.isEmpty()){
            for (ZkPointDataDTO o : list){
                GeoPoint point = new GeoPoint(Double.valueOf(o.getZKX()),Double.valueOf(o.getZKY()));
                Map<String,Object> properties = new HashMap<>();
                properties.put("dataIndex",o.getDataIndex()+"");
                properties.put("settingId",o.getSettingId()+"");
                point.setProperties(properties);
                pointList.add(point);
            }
            double[][] doubles = zkfw.toArray(new double[zkfw.size()][2]);
            GeoPolygon geoPolygon = new GeoPolygon(doubles);
            List<GeoPoint> intersects = spatialRelationship.intersects(pointList, geoPolygon);
            //组装数据
            for (GeoPoint geoPoint:intersects) {
                ZkPointDataDTO zkDataDTO = new ZkPointDataDTO();
                zkDataDTO.setDataIndex(geoPoint.getProperties().getProperty("dataIndex"));
                zkDataDTO.setSettingId(geoPoint.getProperties().getProperty("settingId"));
                zkDataDTO.setZKX(String.valueOf(geoPoint.getX()));
                zkDataDTO.setZKY(String.valueOf(geoPoint.getY()));
                listZks.add(zkDataDTO);
            }
            return listZks;
        }
        return list;
    }

    private String getCodes(String code){
        List<String> list = new ArrayList<>();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            String[] codeArr = code.split(",");
            for (String str:codeArr) {
                if(StringUtils.isBlank(str)){
                    continue;
                }
                TabArea tabArea = boreholeQueryMapper.getAreaByCode(str.substring(0,6));
                Integer grade = tabArea.getGrade();
                switch (grade){
                    case 1:
                        String codeStr1 = boreholeQueryMapper.getCodes(str.substring(0,2));
                        if(!StringUtils.isBlank(codeStr1)){
                            list.add(codeStr1);
                        }
                        break;
                    case 2:
                        String codeStr2 = boreholeQueryMapper.getCodes(str.substring(0,4));
                        if(!StringUtils.isBlank(codeStr2)){
                            list.remove(codeStr2.substring(0,2));
                            list.add(codeStr2);
                        }
                        break;
                    default:
                        String codeStr3 = boreholeQueryMapper.getCodes(str.substring(0,6));
                        if(!StringUtils.isBlank(codeStr3)){
                            list.remove(codeStr3.substring(0,4));
                            list.add(codeStr3);
                        }
                        break;
                }
            }
            return String.join(",",list);
        }
        return "";
    }

    @Override
    public Integer broeHoleNum(QueryDataDTO dto) {
        String code = dto.getCode();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            dto.setCode(getCodes(code));
        }
        return boreholeQueryMapper.broeHoleNum(dto);
    }

    @Override
    public Integer broeHole2DNum(QueryDataDTO dto) {
        String code = dto.getCode();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            dto.setCode(getCodes(code));
        }
        return boreholeQueryMapper.broeHole2DNum(dto);
    }

    @Override
    public List<TabProjectDTO> boreHoleProject(QueryDataDTO dto) {
        String code = dto.getCode();
        //如果code为空，则查询所有数据
        if(!StringUtils.isBlank(code)){
            dto.setCode(getCodes(code));
        }
        List<TabProjectDTO> list = boreholeQueryMapper.boreHoleProject(dto);
        //过滤点范围
        SpatialRelationship spatialRelationship = new SpatialRelationship();
        List<GeoPoint> pointList = new ArrayList<>();
        List<double[]> zkfw = dto.getScope();
        List<TabProjectDTO> listZks = new ArrayList<>();
        if(null !=zkfw && !zkfw.isEmpty()){
            for (TabProjectDTO o : list){
                GeoPoint point = new GeoPoint(Double.valueOf(o.getZKX()),Double.valueOf(o.getZKY()));
                Map<String,Object> properties = new HashMap<>();
                properties.put("GCMC",o.getGCMC());
                point.setProperties(properties);
                pointList.add(point);
            }
            double[][] doubles = zkfw.toArray(new double[zkfw.size()][2]);
            GeoPolygon geoPolygon = new GeoPolygon(doubles);
            List<GeoPoint> intersects = spatialRelationship.intersects(pointList, geoPolygon);
            //组装数据
            for (GeoPoint geoPoint:intersects) {
                Map<String, Object> map = new HashMap<String, Object>((Map) geoPoint.getProperties());
                TabProjectDTO zkDataDTO = new TabProjectDTO();
                zkDataDTO.setGCMC(String.valueOf(map.get("GCMC")));
                listZks.add(zkDataDTO);
            }
            return listZks;
        }
        return list;
    }


    @Override
    @Async
    public void upZkCode() {
        List<Object> list = boreholeQueryMapper.getUpZk();
        for (Object o:list){
            Map<String, Object> m = (Map<String, Object>) o;
            String point = "POINT("+((Map<String, Object>) o).get("zkx")+" "+((Map<String, Object>) o).get("zky")+")";
            if(StringUtils.isBlank(point)) continue;
            TabArea tabArea = boreholeQueryMapper.getAreaByPoint(point);
            boreholeQueryMapper.upZk(null == tabArea?null:tabArea.getCode(),m.get("id").toString());
        }
    }

    @Override
    @Async
    public Future<List<ZkPointDataDTO>> boreHolePointF(QueryDataDTO dto) {
        if(null != dto.getPage() && null != dto.getLimit()){
            dto.setPage((dto.getPage()-1)*dto.getLimit());
        }
        List<ZkPointDataDTO> list =  this.boreHolePoint(dto);
        return new AsyncResult<>(list);
    }

    @Override
    @Async
    public Future<List<ZkDataDTO>> boreHoleF(QueryDataDTO dto) throws Exception {
        if(null != dto.getPage() && null != dto.getLimit()){
            dto.setPage((dto.getPage()-1)*dto.getLimit());
        }
        List<ZkDataDTO> list =  this.boreHole(dto);
        return new AsyncResult<>(list);
    }
}
